import {
  join,
  normalize,
  parseJson,
  Path,
  strings,
} from '@angular-devkit/core';
import {
  apply,
  branchAndMerge,
  chain,
  mergeWith,
  move,
  noop,
  Rule,
  SchematicsException,
  Source,
  template,
  Tree,
  url,
} from '@angular-devkit/schematics';
import * as fse from 'fs-extra';
import {
  DEFAULT_DIR_ENTRY_APP,
  DEFAULT_LANGUAGE,
  DEFAULT_LIB_PATH,
  DEFAULT_PACKAGES_PATH,
  DEFAULT_PATH_NAME,
  PROJECT_TYPE,
  TEST_ENV,
} from '../defaults';
import { SimplePageOptions } from './simple-page.schema';
import { removeTemplateExt } from '../../utils/source-root.helpers';

// type UpdateJsonFn<T> = (obj: T) => T | void;

// interface CpaasPackageInfoItem{
//   name: string;
// }

// interface CpaasConfigPartialType {
//   packages: CpaasPackageInfoItem[];
// }

export function main(options: SimplePageOptions): Rule {
  const packageName = getAppNameFromPackageJson();
  options = transform(options);
  options.packageName = strings.dasherize(`${packageName}`);
  return chain([
    // updateTsConfig(),
    // updateCpaasConfig(options, packageName),
    updateRouterConfig(options),
    // (tree, context) =>
    //   isMonorepo(tree)
    //     ? noop()(tree, context)
    //     : chain([
    //         branchAndMerge(mergeWith(generateWorkspace(options, appName))),
    //         moveDefaultAppToApps(options.path, appName, options.sourceRoot),
    //       ])(tree, context),
    // addAppsToCliOptions(options.path, options.name, appName),
    branchAndMerge(mergeWith(generate(options))),
  ]);
}

function getAppNameFromPackageJson(): string {
  try {
    const packageFile = './package.json';
    // console.log(packageFile);
    // process.exit();
    if (!fse.existsSync(packageFile)) {
      return DEFAULT_DIR_ENTRY_APP;
    }
    const packageJson = fse.readJsonSync(packageFile);
    if (!packageJson.name) {
      return DEFAULT_DIR_ENTRY_APP;
    }
    let name = packageJson.name;
    name = name.replace(/[^\w.]+/g, '-').replace(/\-+/g, '-');
    return name[0] === '-' ? name.substr(1) : name;
  } catch (e) {
    return DEFAULT_DIR_ENTRY_APP;
  }
}

function transform(options: SimplePageOptions): SimplePageOptions {
  const target: SimplePageOptions = Object.assign({}, options);
  // const defaultSourceRoot =
  //   options.rootDir !== undefined ? options.rootDir : DEFAULT_PACKAGES_PATH;

  if (!target.name) {
    throw new SchematicsException('Option (name) is required.');
  }
  target.language = !!target.language ? target.language : DEFAULT_LANGUAGE;
  target.name = strings.dasherize(target.name);
  target.pageName = target.name;
  // target.path =
  //   target.path !== undefined
  //     ? join(normalize(defaultSourceRoot), target.path)
  //     : normalize(defaultSourceRoot);

  return target;
}

// function updateCpaasConfig(options: SimplePageOptions, defaultAppName: string) {
//   return (host: Tree) => {
//     if (!host.exists('.cpaasrc.json')) {
//       return host;
//     }
//     return updateJsonFile(
//       host,
//       '.cpaasrc.json',
//       (cpaasrc: CpaasConfigPartialType) => {
//         if(!cpaasrc.packages || cpaasrc.packages.find(item => item.name === options.packageName)) {
//           return cpaasrc;
//         }
//         cpaasrc.packages = [
//           {
//             name: options.packageName,
//           },
//           ...cpaasrc.packages,
//         ];
//         return cpaasrc;
//       },
//     );
//   };
// }

function updateRouterConfig(options: SimplePageOptions) {
  return (host: Tree) => {
    const routerFileName = 'src/config/routers.ts';
    if (!host.exists(routerFileName)) {
      return host;
    }
    const routerSrc = host.read(routerFileName).toString('utf-8');
    const importStatement = `import ${strings.camelize(
      options.pageName
    )}RouterConfig from '../pages/${strings.dasherize(
      options.pageName
    )}/routers';\n`;
    const expendStatement = `\n  ...${strings.camelize(
      options.pageName
    )}RouterConfig,\n`;
    const routerResult = importStatement
      .concat(routerSrc)
      .replace(/(?<=\/\/ Insert New Router.*)\n/, expendStatement);
    host.overwrite(routerFileName, routerResult);
    return host;
  };
}

// function updateRouterConfigFile(
//   scripts: Record<string, any>,
//   options: SimplePageOptions,
//   defaultAppName: string,
// ) {
//   scripts[options.packageName] = '0.0.1';
// }

function generate(options: SimplePageOptions): Source {
  // const path = join(options.path as Path, options.packageName);

  return apply(url(join('./files' as Path, options.language)), [
    template({
      ...strings,
      ...options,
    }),
    // move(path),
    removeTemplateExt(),
  ]);
}
